{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e49f1e0d",
   "metadata": {},
   "source": [
    "# Robocorp\n",
    "\n",
    "This notebook covers how to get started with [Robocorp Action Server](https://github.com/robocorp/robocorp) action toolkit and LangChain.\n",
    "\n",
    "Robocorp is the easiest way to extend the capabilities of AI agents, assistants and copilots with custom actions.\n",
    "\n",
    "## Installation\n",
    "\n",
    "First, see the [Robocorp Quickstart](https://github.com/robocorp/robocorp#quickstart) on how to setup `Action Server` and create your Actions.\n",
    "\n",
    "In your LangChain application, install the `langchain-robocorp` package: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4c3bef91",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# Install package\n",
    "%pip install --upgrade --quiet langchain-robocorp"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd53ad19-4a62-46d1-a2f7-151cfd282590",
   "metadata": {},
   "source": [
    "When you create the new `Action Server` following the above quickstart.\n",
    "\n",
    "It will create a directory with files, including `action.py`.\n",
    "\n",
    "We can add python function as actions as shown [here](https://github.com/robocorp/robocorp/tree/master/actions#describe-your-action).\n",
    "\n",
    "Let's add a dummy function to `action.py`.\n",
    "\n",
    "```\n",
    "@action\n",
    "def get_weather_forecast(city: str, days: int, scale: str = \"celsius\") -> str:\n",
    "    \"\"\"\n",
    "    Returns weather conditions forecast for a given city.\n",
    "\n",
    "    Args:\n",
    "        city (str): Target city to get the weather conditions for\n",
    "        days: How many day forecast to return\n",
    "        scale (str): Temperature scale to use, should be one of \"celsius\" or \"fahrenheit\"\n",
    "\n",
    "    Returns:\n",
    "        str: The requested weather conditions forecast\n",
    "    \"\"\"\n",
    "    return \"75F and sunny :)\"\n",
    "```\n",
    "\n",
    "We then start the server:\n",
    "\n",
    "```\n",
    "action-server start\n",
    "```\n",
    "\n",
    "And we can see: \n",
    "\n",
    "```\n",
    "Found new action: get_weather_forecast\n",
    "\n",
    "```\n",
    "\n",
    "Test locally by going to the server running at `http://localhost:8080` and use the UI to run the function."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b4f3e15",
   "metadata": {},
   "source": [
    "## Environment Setup\n",
    "\n",
    "Optionally you can set the following environment variables:\n",
    "\n",
    "- `LANGCHAIN_TRACING_V2=true`: To enable LangSmith log run tracing that can also be bind to respective Action Server action run logs. See [LangSmith documentation](https://docs.smith.langchain.com/tracing#log-runs) for more.\n",
    "\n",
    "## Usage\n",
    "\n",
    "We started the local action server, above, running on `http://localhost:8080`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "62e0dbc3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `robocorp_action_server_get_weather_forecast` with `{'city': 'San Francisco', 'days': 1, 'scale': 'fahrenheit'}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3m\"75F and sunny :)\"\u001b[0m\u001b[32;1m\u001b[1;3mThe current weather today in San Francisco is 75F and sunny.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': 'What is the current weather today in San Francisco in fahrenheit?',\n",
       " 'output': 'The current weather today in San Francisco is 75F and sunny.'}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.agents import AgentExecutor, OpenAIFunctionsAgent\n",
    "from langchain_core.messages import SystemMessage\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_robocorp import ActionServerToolkit\n",
    "\n",
    "# Initialize LLM chat model\n",
    "llm = ChatOpenAI(model=\"gpt-4\", temperature=0)\n",
    "\n",
    "# Initialize Action Server Toolkit\n",
    "toolkit = ActionServerToolkit(url=\"http://localhost:8080\", report_trace=True)\n",
    "tools = toolkit.get_tools()\n",
    "\n",
    "# Initialize Agent\n",
    "system_message = SystemMessage(content=\"You are a helpful assistant\")\n",
    "prompt = OpenAIFunctionsAgent.create_prompt(system_message)\n",
    "agent = OpenAIFunctionsAgent(llm=llm, prompt=prompt, tools=tools)\n",
    "\n",
    "executor = AgentExecutor(agent=agent, tools=tools, verbose=True)\n",
    "\n",
    "executor.invoke(\"What is the current weather today in San Francisco in fahrenheit?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa9fbbf5",
   "metadata": {},
   "source": [
    "### Single input tools\n",
    "\n",
    "By default `toolkit.get_tools()` will return the actions as Structured Tools. \n",
    "\n",
    "To return single input tools, pass a Chat model to be used for processing the inputs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "1dc7db86",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize single input Action Server Toolkit\n",
    "toolkit = ActionServerToolkit(url=\"http://localhost:8080\")\n",
    "tools = toolkit.get_tools(llm=llm)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
